home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / server_links.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  7KB  |  296 lines

  1. /* Copyright (C) 2000 edwards@bitchx.dimension6.com
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    Modified by drscholl@users.sourceforge.net 2/25/2000.
  6.  
  7.    $Id: server_links.c,v 1.28 2001/01/08 10:15:15 drscholl Exp $ */
  8.  
  9. #include <string.h>
  10. #if !defined( WIN32) || defined(__CYGWIN__)
  11. #include <sys/time.h>
  12. #include <unistd.h>
  13. #else
  14. #include <time.h>
  15. #endif
  16. #include <stdlib.h>
  17. #include <limits.h>
  18. #include <errno.h>
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "opennap.h"
  22. #include "debug.h"
  23.  
  24. #if defined( WIN32) && !defined(__CYGWIN__)
  25. /* emulate gettimeofday, only uses seconds since I can't figure out how
  26.  * to get sub-second accurracy
  27.  */
  28. static int
  29. gettimeofday (struct timeval *ptr, void *unused)
  30. {
  31.     memset (ptr, 0, sizeof (struct timeval));
  32.  
  33.     ptr->tv_sec = time (0);
  34.     return 0;
  35. }
  36. #endif
  37.  
  38. /* 10112 */
  39. /* process client request for server links */
  40. HANDLER (server_links)
  41. {
  42.     LIST   *list;
  43.     LINK   *slink;
  44.     CONNECTION *serv;
  45.  
  46.     (void) tag;
  47.     (void) len;
  48.     (void) pkt;
  49.     CHECK_USER_CLASS ("server_links");
  50.     ASSERT (validate_connection (con));
  51.  
  52.     /* first dump directly connected servers */
  53.     for (list = Servers; list; list = list->next)
  54.     {
  55.     serv = list->data;
  56.     send_cmd (con, MSG_SERVER_LINKS, "%s %hu %s %hu 1",
  57.           Server_Name, get_local_port (serv->fd), serv->host,
  58.           serv->port);
  59.     }
  60.  
  61.     /* dump remote servers */
  62.     for (list = Server_Links; list; list = list->next)
  63.     {
  64.     slink = list->data;
  65.     send_cmd (con, MSG_SERVER_LINKS, "%s %hu %s %hu %d", slink->server,
  66.           slink->port, slink->peer, slink->peerport, slink->hops);
  67.     }
  68.  
  69.     /* terminate the list */
  70.     send_cmd (con, MSG_SERVER_LINKS, "");
  71. }
  72.  
  73. /* 750 [ :<sender> ] <server> [args] */
  74. HANDLER (ping_server)
  75. {
  76.     USER   *sender;
  77.     char   *recip;
  78.     char   *sender_name;
  79.  
  80.     (void) len;
  81.     ASSERT (validate_connection (con));
  82.     if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
  83.     return;
  84.     recip = next_arg (&pkt);
  85.     if (!recip || !strcasecmp (Server_Name, recip))
  86.     {
  87.     /* local server is being pinged */
  88.     if (ISUSER (con))
  89.         /* local user issued request */
  90.         send_cmd (con, tag, "%s %s", Server_Name, NONULL (pkt));
  91.     else
  92.         /* use inter-server pong message to reply */
  93.         send_cmd (con, MSG_SERVER_SERVER_PONG,
  94.               ":%s %s %s", Server_Name, sender_name, NONULL (pkt));
  95.     }
  96.     else if (is_server (recip))
  97.     {
  98.     /* client request from remote server to remote server */
  99.     pass_message_args (con, tag, ":%s %s %s", sender_name, recip,
  100.                NONULL (pkt));
  101.     }
  102.     else if (ISUSER (con))
  103.     send_cmd (con, MSG_SERVER_NOSUCH,
  104.           "server ping failed: no such server");
  105.     else
  106.     log
  107.         ("ping_server: recv'd ping for unknown server %s from server %s (originated from %s)",
  108.          recip, con->host, sender_name);
  109. }
  110.  
  111. /* 10022 :<server> <recip> [args]
  112.  * server->server pong response
  113.  */
  114. HANDLER (server_pong)
  115. {
  116.     char   *server;
  117.     char   *nick;
  118.     USER   *user;
  119.  
  120.     CHECK_SERVER_CLASS ("server_pong");
  121.  
  122.     (void) len;
  123.     server = next_arg (&pkt);
  124.     nick = next_arg (&pkt);
  125.     if (!server || !nick)
  126.     {
  127.     log ("server_pong: error, missing argument(s)");
  128.     return;
  129.     }
  130.     server++;            /* skip the colon */
  131.  
  132.     user = hash_lookup (Users, nick);
  133.     if (user)
  134.     {
  135.     if (ISUSER (user->con))
  136.         /* user is local, deliver the response */
  137.         send_cmd (user->con, MSG_CLIENT_PING_SERVER, "%s %s",
  138.               server, NONULL (pkt));
  139.     else
  140.         /* route directly to the server that the user is behind */
  141.         send_cmd (user->con, tag, ":%s %s %s",
  142.               server, user->nick, NONULL (pkt));
  143.     }
  144.     /* recip is not a user, check to see if it's the local server */
  145.     else if (!strcasecmp (Server_Name, nick))
  146.     {
  147.     char   *secs;
  148.     char   *usecs;
  149.  
  150.     /* response is for the local server.  do lag checking  */
  151.     secs = next_arg (&pkt);
  152.     usecs = next_arg (&pkt);
  153.     if (secs && usecs)
  154.     {
  155.         struct timeval tv;
  156.  
  157.         gettimeofday (&tv, NULL);
  158.  
  159.         notify_mods (PINGLOG_MODE, "Pong from server %s [%d millisecs]",
  160.              server,
  161.              (int) ((((tv.tv_sec - atoi (secs)) * 1000000. +
  162.               tv.tv_usec - atoi (usecs)) / 1000000.) * 1000.));
  163.     }
  164.     else
  165.         log ("server_pong: pong from %s with invalid args", con->host);
  166.     }
  167.     else if (is_server (nick))
  168.     pass_message_args (con, tag, ":%s %s %s", server, nick, NONULL (pkt));
  169.     else
  170.     log ("server_pong: unknown target %s from server %s", nick,
  171.          con->host);
  172. }
  173.  
  174. /* this currently doesn't do anything more than ping the peer servers and
  175.  * report the lag times to mods+
  176.  */
  177. void
  178. lag_detect (void *p)
  179. {
  180.     LIST   *list;
  181.     CONNECTION *con;
  182.     struct timeval tv;
  183.  
  184.     (void) p;            /* unused */
  185.  
  186.     if (Servers)
  187.     {
  188.     gettimeofday (&tv, 0);
  189.     /* ping all of our peer servers */
  190.     for (list = Servers; list; list = list->next)
  191.     {
  192.         con = list->data;
  193.         send_cmd (con, MSG_CLIENT_PING_SERVER, ":%s %s %u %u",
  194.               Server_Name, con->host, tv.tv_sec, tv.tv_usec);
  195.     }
  196.     notify_mods (PINGLOG_MODE, "Pinging all peer servers...");
  197.     }
  198. }
  199.  
  200. /* 10120
  201.  * ping all peer servers
  202.  */
  203. HANDLER (ping_all_servers)
  204. {
  205.     (void) tag;
  206.     (void) len;
  207.     (void) pkt;
  208.     CHECK_USER_CLASS ("ping_all_servers");
  209.     if (con->user->level < LEVEL_MODERATOR)
  210.     {
  211.     send_cmd (con, MSG_SERVER_NOSUCH,
  212.           "ping all servers failed: permission denied");
  213.     return;
  214.     }
  215.     lag_detect (0);
  216. }
  217.  
  218. void
  219. free_server_auth (server_auth_t * auth)
  220. {
  221.     FREE (auth->name);
  222.     if (auth->alias)
  223.     FREE (auth->alias);
  224.     FREE (auth->their_pass);
  225.     FREE (auth->my_pass);
  226.     FREE (auth);
  227. }
  228.  
  229. void
  230. load_server_auth (void)
  231. {
  232.     char    path[_POSIX_PATH_MAX];
  233.     FILE   *fp;
  234.     int     ac;
  235.     char   *av[10];
  236.     int     line = 0;
  237.     server_auth_t *slink;
  238.     LIST   *list;
  239.  
  240.     list_free (Server_Auth, (list_destroy_t) free_server_auth);
  241.     Server_Auth = 0;
  242.  
  243.     snprintf (path, sizeof (path), "%s/servers", Config_Dir);
  244.     fp = fopen (path, "r");
  245.     if (!fp)
  246.     {
  247.     if (errno != ENOENT)
  248.         logerr ("load_server_auth_info", path);
  249.     return;
  250.     }
  251.     log ("load_server_auth_info: reading %s", path);
  252.     Buf[sizeof (Buf) - 1] = 0;
  253.     while (fgets (Buf, sizeof (Buf) - 1, fp))
  254.     {
  255.     line++;
  256.     if (Buf[0] == '#' || isspace (Buf[0]))
  257.         continue;
  258.     ac = split_line (av, FIELDS (av), Buf);
  259.     if (ac >= 3)
  260.     {
  261.         slink = CALLOC (1, sizeof (server_auth_t));
  262.         slink->name = STRDUP (av[0]);
  263.         slink->their_pass = STRDUP (av[1]);
  264.         slink->my_pass = STRDUP (av[2]);
  265.         if (ac >= 4)
  266.         {
  267.         slink->port = atoi (av[3]);
  268.         if (slink->port < 1 || slink->port > 65535)
  269.         {
  270.             log ("load_server_auth_info: invalid port at line %d",
  271.              line);
  272.             slink->port = 8888;
  273.         }
  274.         /* if a nickname for the server is given, save it so that
  275.          * we can sheild the real dns name from the masses (used
  276.          * for routing-only servers which we want to make pratically
  277.          * invisible).
  278.          */
  279.         if (ac >= 5)
  280.             slink->alias = STRDUP (av[4]);
  281.         }
  282.         else
  283.         slink->port = 8888;
  284.         list = CALLOC (1, sizeof (LIST));
  285.         list->data = slink;
  286.         list->next = Server_Auth;
  287.         Server_Auth = list;
  288.     }
  289.     else
  290.         log ("load_server_auth_info: too few parameters at line %d",
  291.          line);
  292.     }
  293.  
  294.     fclose (fp);
  295. }
  296.